// Copyright (c) 2007, Commerce360, Inc.
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without 
// modification, are permitted provided that the following conditions 
// are met:
//
//     * Redistributions of source code must retain the above copyright 
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright 
//       notice, this list of conditions and the following disclaimer in 
//       the documentation and/or other materials provided with the 
//       distribution.
//     * Neither the name of the Commerce360, Inc. nor the names of its 
//       contributors may be used to endorse or promote products derived 
//       from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
import org.kohsuke.args4j.Option;
import org.kohsuke.args4j.CmdLineParser;
import org.kohsuke.args4j.CmdLineException;
import org.apache.axis.encoding.Base64;
import com.nettica.www.DNS.DnsApi.*;

public class Nettica {
    @Option(name="-u", required=true, usage="Nettica username")
    private String username;
    @Option(name="-p", required=true, usage="Nettica password")
    private String password;
    @Option(name="-c", required=true, usage="Command to execute ('info', 'list', 'add', 'delete')")
    private String command;
    @Option(name="-d", usage="Domain name")
    private String domainname;
    @Option(name="-h", usage="Hostname")
    private String hostname;
    @Option(name="-i", usage="IPv4 address")
    private String ipv4;
    @Option(name="-t", usage="TTL value (in seconds)")
    private int ttl = -1;

    public String decode_status(int status) {
	switch (status) {
	case 200:
	    return "Success";
	case 401:
	    return "Access denied";
	case 404:
	    return "Not found";
	case 431:
	    return "Record already exists";
	case 432:
	    return "Invalid record type. Must be \"A\",\"MX\",\"CNAME\",\"F\",\"TXT\",\"SRV\"";
	case 450:
	    return "No service";
	case 460:
	    return "Your service has expired";
	default:
	    return "Unknown status code";
	}
    }

    public void change_a_record(int op) {
	try {
	    DnsApiAsmxSoap client = (new DnsApiAsmxLocator()).getDnsApiAsmxSoap();
	    DomainRecord d = new DomainRecord();
	    DnsResult result = null;
	    d.setRecordType("A");
	    d.setDomainName(domainname);
	    d.setHostName(hostname);
	    d.setData(ipv4);
	    d.setTTL(ttl);
	    if (op == 0) {
		result = client.addRecord(username, password, d);
	    } else if (op == 1) {
		result = client.deleteRecord(username, password, d);
	    }
	    System.out.println(decode_status(result.getStatus()));
	} catch (javax.xml.rpc.ServiceException e) {
	    System.err.println("error: RPC Service exception: " + e.getMessage());
	} catch (java.rmi.RemoteException e) {
	    System.err.println("error: RMI Remote exception: " + e.getMessage());
	}
    }

    public void list_a_record() {
	try {
	    DnsApiAsmxSoap client = (new DnsApiAsmxLocator()).getDnsApiAsmxSoap();
	    DomainResult info = null;
	    String host = domainname;
	    if (hostname != null) {
		host = hostname + "." + host;
	    }
	    info = client.listDomain(username, password, host);
	    if (info.getResult().getStatus() != 200) {
		System.err.println("error: failed to retrieve domain list: " + decode_status(info.getResult().getStatus()));
	    } else {
		for (DomainRecord r : info.getRecord()) {
		    System.out.println(r.getHostName() + "." + r.getDomainName() + " " + r.getData() + " " + r.getTTL());
		}
	    }
	} catch (javax.xml.rpc.ServiceException e) {
	    System.err.println("error: RPC Service exception: " + e.getMessage());
	} catch (java.rmi.RemoteException e) {
	    System.err.println("error: RMI Remote exception: " + e.getMessage());
	}
    }

    public void get_service_info() {
	try {
	    DnsApiAsmxSoap client = (new DnsApiAsmxLocator()).getDnsApiAsmxSoap();
	    ServiceResult info = client.getServiceInfo(username, password);
	    DnsResult result = info.getResult();
	    int status = result.getStatus();
	    if (status != 200) {
		System.err.println("error: GetServiceInfo request failed with status " + status + ": " + decode_status(status));
	    } else {
		System.out.println("Remaining Credits: " + info.getRemainingCredits());
		System.out.println("Total Credits:     " + info.getTotalCredits());
		System.out.println("Renewal Date:      " + info.getServiceRenewalDate().getTime().toString());
	    }
	} catch (javax.xml.rpc.ServiceException e) {
	    System.err.println("error: RPC Service exception: " + e.getMessage());
	} catch (java.rmi.RemoteException e) {
	    System.err.println("error: RMI Remote exception: " + e.getMessage());
	}
    }

    public void doMain(String[] args) {
	CmdLineParser parser = new CmdLineParser(this);
	parser.setUsageWidth(80);
	try {
	    parser.parseArgument(args);
	} catch (CmdLineException e) {
	    System.err.println(e.getMessage());
	    System.err.println();
	    System.err.println("java Nettica [options]");
	    parser.printUsage(System.err);
	    System.err.println();
	    System.exit(1);
	}
	password = Base64.encode(password.getBytes());

	if (command.equals("info")) {
	    get_service_info();
	} else if (command.equals("list")) {
	    if (domainname == null) {
		System.err.println("error: missing domainname");
		System.exit(1);
	    }
	    list_a_record();
	} else if (command.equals("add")) {
	    if (domainname == null || hostname == null || ipv4 == null || ttl == -1) {
		System.err.println("error: missing domainname, hostname, IP or TTL");
		System.exit(1);
	    }
	    change_a_record(0);
	} else if (command.equals("delete")) {
	    if (domainname == null || hostname == null || ipv4 == null) {
		System.err.println("error: missing domainname, hostname or IP");
		System.exit(1);
	    }
	    ttl = 0;
	    change_a_record(1);
	} else {
	    System.err.println("error: invalid command (good: info, add, delete)");
	    System.exit(1);
	}
    }

    public static void main(String[] args) {
	new Nettica().doMain(args);
    }
}

